package com.itheima.stock.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: geek
 * @Date: 2024/11/25/3:43 PM
 * @Description: 自定义redis 序列化方式，默认采用 jdk的序列化方式
 *               JDK 序列化问题：
 *                  1、阅读体验差
 *                  2、序列化后内容体积大，占用内存大。
 */
@Configuration
public class RedisCacheConfig {
    /**
     * 配置redisTemplate bean，自定义数据的序列化的方式
     * @param redisConnectionFactory 连接redis的工厂，底层有场景依赖启动时，自动加载
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(@Autowired RedisConnectionFactory redisConnectionFactory) {
        //1.构建RedisTemplate模板对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        //2.构建序列化的对象，比如序列化转json的一些vo等
        Jackson2JsonRedisSerializer objecterializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        //禁止将Date转Timestameps
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        //属性值为null的属性不做序列化处理
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //设置暴力访问任意方法
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //仅仅序列化对象的属性，且属性不可为final修饰
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        objecterializer.setObjectMapper(mapper);
        //3.构建普通字符串序列化对象
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        //4.为不同的数据结构设置不同的序列化方案
        //设置value序列化方式
        template.setValueSerializer(objecterializer);
        //设置key序列化方式
        template.setKeySerializer(stringSerializer);
        //设置hash中field字段序列化方式
        template.setHashKeySerializer(stringSerializer);
        //设置hash中value的序列化方式
        template.setHashValueSerializer(objecterializer);
        //5.初始化参数设置
        template.afterPropertiesSet();
        return template;
    }
}
